package perform.broker;

import java.sql.Connection;
import java.util.List;

import perform.criterion.Criterion;
import perform.criterion.Order;
import perform.type.Type;
import perform.type.Wrapper;
import perform.utilities.ResultProcessor;

public abstract class AbstractDatabaseBroker implements DatabaseBroker {

	protected ResultProcessor processor;
	protected Wrapper wrapper;

	protected AbstractDatabaseBroker() {
		processor = new ResultProcessor();
		wrapper = new Wrapper();
	}

	@Override
	public <T extends Type> T save(T type, Connection connection)
			throws Exception {
		checkManyToOne(type, connection);
		checkOneToOne(type, connection);
		if (!wrapper.isSaved(type)) {
			type = insert(type, connection);
		}
		checkOneToMany(type, connection);
		checkManyToMany(type, connection);
		return type;
	}

	protected abstract <S extends Type, T extends Type> void checkManyToOne(
			S type, Connection connection) throws Exception;

	protected abstract <S extends Type, T extends Type> void checkOneToOne(
			S type, Connection connection) throws Exception;

	protected abstract <S extends Type> S insert(S type, Connection connection)
			throws Exception;

	protected abstract <S extends Type, T extends Type> void checkOneToMany(
			S type, Connection connection) throws Exception;

	protected abstract <S extends Type, T extends Type> void checkManyToMany(
			S type, Connection connection) throws Exception;

	@Override
	public abstract <T extends Type> void update(T type, Connection connection)
			throws Exception;

	@Override
	public abstract <T extends Type> void delete(T type, Connection connection)
			throws Exception;

	@Override
	public abstract <T extends Type> T get(T type, Connection connection)
			throws Exception;

	@Override
	public abstract <T extends Type> List<T> get(Class<T> clazz,
			Criterion criterion, Connection connection) throws Exception;

	@Override
	public abstract <T extends Type> List<T> get(Class<T> clazz,
			Criterion criterion, Order order, Connection connection)
			throws Exception;

	@Override
	public abstract <T extends Type> List<T> get(Class<T> clazz,
			Criterion criterion, Order order, int lowLimit, int highLimit,
			Connection connection) throws Exception;

	@Override
	public abstract <T extends Type> List<T> get(Class<T> clazz,
			String criteria, Connection connection) throws Exception;

	@Override
	public abstract <T extends Type> List<T> get(Class<T> clazz,
			String criteria, Order order, Connection connection)
			throws Exception;

	public abstract <T extends Type> List<T> get(Class<T> clazz,
			String criteria, Order order, int lowLimit, int highLimit,
			Connection connection) throws Exception;

	public abstract <T extends Type> List<T> getCustom(Class<T> clazz,
			String from, Connection connection) throws Exception;

	public abstract void customUpdate(String query, Connection connection)
			throws Exception;

}
